package com.zhike.service.im.manager;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.zhike.common.dto.GroupInfo4Cache;
import com.zhike.common.dto.GroupMember4Cache;
import com.zhike.common.dto.GroupMemberEntity;
import com.zhike.common.dto.MsgBody4Group;
import com.zhike.common.dto.MsgBodyRoot;
import com.zhike.common.model.ChatSession;
import com.zhike.common.model.Device;
import com.zhike.common.repository.HistoryMessage;
import com.zhike.common.vo.UserInfo4Cache;
import com.zhike.mobileimsdk.server.protocal.Protocal;
import com.zhike.service.im.concurrent.CommonConcurrentExecutor;
import com.zhike.service.im.concurrent.GroupSenderConcurrentExecutor;
import com.zhike.service.messages.EsSearchService;
import com.zhike.service.messages.IChatSessionService;
import com.zhike.service.messages.IHistoryMessageRepository;
import com.zhike.utils.MessageHelper;
import com.zhike.utils.cache.GroupsInfoCacheProvider;
import com.zhike.utils.cache.GroupsMembersCacheProvider;
import com.zhike.utils.cache.UsersInfoCacheProvider;
import com.zhike.utils.manager.UsersStatusManager;

import cn.hutool.core.util.IdUtil;
import lombok.extern.slf4j.Slf4j;

@Slf4j
@Component
public class ChatManager4Group {
    @Autowired
    private MessageHelper messageHelper;

    @Autowired
    private UsersInfoCacheProvider usersInfoCacheProvider;

    @Autowired
    private GroupsInfoCacheProvider groupsInfoCacheProvider;

    @Autowired
    private UsersStatusManager usersStatusManager;

    @Autowired
    private GroupsMembersCacheProvider groupsMembersCacheProvider;

    @Autowired
    private MessageRecordManager messageRecordManager;

    @Autowired
    private IChatSessionService chatSessionService;

    @Autowired
    private EsSearchService esSearchService;

    @Autowired
    private IHistoryMessageRepository historyMessageRepository;

    /**
     * 【邀请新人入群时的批量通知】向被邀请入群的群成员批量发出已成功加群的通知、向其它群员
     * 发出新入群成员通知（已支持离线存储）。
     * 
     * @param newJoinedMemberList 被邀请人列表（用于接受通知：你加入成功了）
     */
    @Deprecated
    public void batchNotification4InviteMembersAsync(String sessionId, String ownerUid, String ownerName,
            ArrayList<GroupMemberEntity> targetMembers,
            ArrayList<GroupMemberEntity> newJoinedMemberList,
            GroupInfo4Cache gc) {
        GroupSenderConcurrentExecutor.getInstance().execute(new Runnable() {

            @Override
            public void run() {
                try {

                    // 通知被邀请者
                    String fp = Protocal.genFingerPrint();
                    for (GroupMemberEntity newJoinedMember : targetMembers) {
                        String newJoinUid = newJoinedMember.getUserId();
                        UserInfo4Cache uc = usersInfoCacheProvider.get(newJoinUid);
                        for (Device device : uc.getDeviceList()) {
                            messageHelper.sendGroupSysCMD4Message(
                                    sessionId,
                                    device.getDeviceNo(),
                                    ownerUid,
                                    ownerName,
                                    gc,
                                    newJoinedMemberList,
                                    fp);
                        }
                        Thread.sleep(1 * 1000);
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }

        });
    }

    /**
     * 群聊/世界频道消息的代码实现代码。
     * <p>
     * 
     * @param dataContent
     */
    public boolean processMT44_OF_GROUP$CHAT$MSG_A$TO$SERVER(final String fingerPrint, final String dataContent) {

        GroupSenderConcurrentExecutor.getInstance().execute(new Runnable() {

            @Override
            public void run() {
                // 解析群组聊天消息
                final MsgBody4Group msgBody = MessageHelper.pareseGroupChatMsg_A$TO$SERVER_Message(dataContent);
                log.debug("[ZKIMChat]【群聊/世界频道】《《《《《！收到了群发消息！》》》》》 ->" + msgBody);
                if (StringUtils.isBlank(msgBody.getT())) {
                    log.error("参数t是空");
                    return;
                }

                String gid = msgBody.getT();
                String f = msgBody.getF();
                Iterator membersToSend = null;

                ConcurrentHashMap<String, GroupMember4Cache> members2Vec = groupsMembersCacheProvider.get(gid);
                membersToSend = members2Vec.keySet().iterator();

                if (membersToSend != null) {
                    while (membersToSend.hasNext()) {
                        String uid = (String) membersToSend.next();
                        UserInfo4Cache uc = usersInfoCacheProvider.get(uid);
                        List<Device> devices = uc.getDeviceList();

                        for (Device d : devices) {
                            if (f.equals(uid)) {
                                // 过滤自己发消息的设备
                                if (msgBody.getM2() != null && msgBody.getM2().equals(d.getDeviceNo())) {
                                    log.debug("过滤群成员设备: {}", msgBody.getM2());
                                    continue;
                                }
                            }
                            try {
                                MessageHelper.SendResultObserver sendResultObserver = new MessageHelper.SendResultObserver() {
                                    @Override
                                    public void update(boolean code, Protocal p) {
                                        if (code) {
                                            log.info("群: {} 消息【投递OK】已成功将uid= {} 的消息实时发送给成员 {}", gid, msgBody.getF(),
                                                    uid);
                                        }
                                    }

                                };
                                if (usersStatusManager.isOnline(d.getDeviceNo())) {
                                    messageHelper.sendGroupChatMsg_SERVER$TO$B_Message(d.getDeviceNo(), msgBody,
                                            sendResultObserver);
                                }

                            } catch (Exception e) {
                                e.printStackTrace();
                            }
                        }

                    }

                    CommonConcurrentExecutor.getInstance().execute(new Runnable() {
                        @Override
                        public void run() {
                            saveGroupMessage(f, gid, dataContent, fingerPrint);
                        }
                    });
                }
            }
        });
        return true;
    }

    private void saveGroupMessage(String fromUid, String gid, String dataContent, String fp) {
        GroupInfo4Cache gc = groupsInfoCacheProvider.get(gid);
        MsgBody4Group msg = MessageHelper.pareseGroupChatMsg_A$TO$SERVER_Message(dataContent);
        ChatSession cs = chatSessionService.selectGroupSession(fromUid, gid);
        if (cs != null) {
            HistoryMessage hm = messageRecordManager.colectGroupMsgAsync(cs.getSessionId(), fromUid,
                    "", gid, MsgBodyRoot.CHAT_TYPE_GROUP$CHAT,
                    msg.getTy(), msg.getM(), fp);
            if (hm != null) {
                chatSessionService.updateGroupSession(hm, gc.getGname(), fromUid);
                esSearchService.insert(hm);
                log.debug("更新会话 {}", hm);
            }

        } else {
            HistoryMessage hmSession = historyMessageRepository.findHistoryMessageByGroup(gid, fromUid);
            String sessionId = IdUtil.getSnowflakeNextIdStr();
            if (hmSession != null) {
                sessionId = hmSession.getSessionId();
            }
            HistoryMessage hm = messageRecordManager.colectGroupMsgAsync(sessionId, fromUid,
                    "", gid, MsgBodyRoot.CHAT_TYPE_GROUP$CHAT,
                    msg.getTy(), msg.getM(), fp);
            if (hm != null) {
                chatSessionService.createGroupSession(hm, gc.getGname(), fromUid);
                esSearchService.insert(hm);
                log.debug("创建会话 {}", hm);
            }
        }
    }

    /**
     * 创建群成功后发送群消息
     * 发送目标：* 在线的所有群成员
     * 
     * @param gmm 群消息管理器
     * @param sm  存储消息 如果不需要存储，传null即可
     * @throws Exception
     */
    public void sendMsgOrSave4Group(GroupMessageManager gmm, StorageMessage sm) throws Exception {
        gmm.sendMessagToGroup(sm);
    }

    public void notify4Group(GroupMessageManager gmm, int typeu, int count) throws Exception {
        gmm.notificationToGroup(typeu, count);
    }

}
